package com.markerhub.controller;


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.markerhub.common.dto.SysMenuDto;
import com.markerhub.common.lang.Const;
import com.markerhub.common.lang.Result;
import com.markerhub.common.utils.SpringContextUtils;
import com.markerhub.entity.SysMenu;
import com.markerhub.entity.SysRoleMenu;
import com.markerhub.entity.SysUser;
import com.markerhub.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 菜单管理Controller
 */
@Api(tags = "菜单管理")
@RestController
@RequestMapping("/api/sys-menu")
public class SysMenuController extends BaseController {

	/**
	 * 用户当前用户的菜单和权限信息
	 * @param principal
	 * @return
	 */
	@ApiOperation(value = "导航菜单", notes = "获取当前用户的导航菜单")
    @GetMapping("/nav")
    public Result nav(HttpServletRequest request) {
        System.out.println("========== 进入导航菜单方法 ==========");
        
        // 1. 尝试从SecurityContext获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        System.out.println("SecurityContext认证对象: " + (authentication != null ? authentication.getClass().getSimpleName() : "null"));
        
        String username = null;
        
        // 检查认证状态
        if (authentication != null) {
            System.out.println("认证状态: " + authentication.isAuthenticated());
            
            // 如果有有效的认证信息，直接获取用户名
            if (authentication.isAuthenticated() && authentication.getPrincipal() instanceof org.springframework.security.core.userdetails.UserDetails) {
                org.springframework.security.core.userdetails.UserDetails userDetails = (org.springframework.security.core.userdetails.UserDetails) authentication.getPrincipal();
                username = userDetails.getUsername();
                System.out.println("1. 从SecurityContext(UserDetails)获取用户名: " + username);
            } else if (authentication.isAuthenticated() && authentication.getPrincipal() instanceof String && !"anonymousUser".equals(authentication.getPrincipal())) {
                username = (String) authentication.getPrincipal();
                System.out.println("2. 从SecurityContext(String)获取用户名: " + username);
            } else {
                System.out.println("3. SecurityContext中没有有效的认证信息，需要从token获取");
            }
        }
        
        // 2. 如果SecurityContext中没有用户名，则从token获取
        if (StrUtil.isBlank(username)) {
            try {
                JwtUtils jwtUtils = SpringContextUtils.getBean(JwtUtils.class);
                String token = null;
                
                // 2.1 从自定义JWT头获取
                String jwtHeader = jwtUtils.getHeader();
                System.out.println("使用的JWT头名称: " + jwtHeader);
                token = request.getHeader(jwtHeader);
                System.out.println("从JWT头获取的token: " + (StrUtil.isBlank(token) ? "空" : "非空"));
                
                // 2.2 如果为空，尝试从Authorization头获取
                if (StrUtil.isBlank(token)) {
                    String authHeader = request.getHeader("Authorization");
                    System.out.println("从Authorization头获取的值: " + (StrUtil.isBlank(authHeader) ? "空" : authHeader));
                    
                    if (StrUtil.isNotBlank(authHeader)) {
                        // 确保正确处理Bearer前缀，忽略大小写
                        if (authHeader.toLowerCase().startsWith("bearer ")) {
                            token = authHeader.substring(7).trim();
                            System.out.println("提取Bearer token: " + (StrUtil.isBlank(token) ? "空" : token.substring(0, Math.min(20, token.length())) + "..."));
                        } else {
                            token = authHeader.trim();
                            System.out.println("直接使用Authorization值作为token: " + (StrUtil.isBlank(token) ? "空" : token.substring(0, Math.min(20, token.length())) + "..."));
                        }
                    }
                }
                
                // 2.3 如果仍然为空，尝试从请求参数获取
                if (StrUtil.isBlank(token)) {
                    token = request.getParameter("token");
                    System.out.println("从请求参数获取的token: " + (StrUtil.isBlank(token) ? "空" : "非空"));
                }
                
                // 3. 从token中解析用户名
                if (StrUtil.isNotBlank(token)) {
                    Claims claims = jwtUtils.getClaimByToken(token);
                    if (claims != null && !jwtUtils.isTokenExpired(claims)) {
                        username = claims.getSubject();
                        System.out.println("从token中解析的用户名: " + username);
                    } else {
                        System.out.println("token无效或已过期");
                        return Result.fail("登录已过期，请重新登录");
                    }
                }
            } catch (Exception e) {
                System.out.println("解析token异常: " + e.getMessage());
                e.printStackTrace();
                return Result.fail("登录状态异常，请重新登录");
            }
        }
        
        // 4. 验证用户名
        if (StrUtil.isBlank(username)) {
            System.out.println("无法获取用户名，返回400错误");
            return Result.fail("未找到用户信息，请重新登录");
        }
        
        // 5. 获取用户信息
        System.out.println("根据用户名" + username + "查询用户信息...");
        SysUser sysUser = sysUserService.getByUsername(username);
        
        if (sysUser == null) {
            System.out.println("用户不存在: " + username);
            return Result.fail("用户不存在");
        }
        
        try {
            // 获取权限信息
            String authorityInfo = sysUserService.getUserAuthorityInfo(sysUser.getId());// ROLE_admin,ROLE_normal,sys:user:list,....
            String[] authorityInfoArray = StringUtils.tokenizeToStringArray(authorityInfo, ",");
            System.out.println("用户权限数量: " + authorityInfoArray.length);
            
            // 获取导航栏信息
            List<SysMenuDto> navs = sysMenuService.getCurrentUserNav();
            System.out.println("获取到菜单数量: " + navs.size());
            
            // 构建返回数据
            return Result.succ(200, "获取导航菜单成功", MapUtil.builder()
                    .put("authoritys", authorityInfoArray)
                    .put("nav", navs)
                    .map()
            );
            
        } catch (Exception e) {
            System.out.println("获取菜单失败: " + e.getMessage());
            e.printStackTrace();
            return Result.fail("获取菜单失败");
        }
    }

	@ApiOperation(value = "获取菜单详情", notes = "根据菜单ID获取菜单详细信息")
	@PreAuthorize("hasAuthority('sys:menu:list')")
	@GetMapping("/detail/{id}")
	public Result detail(@PathVariable(name = "id") Long id) {
		return Result.succ(200, "获取菜单信息成功", sysMenuService.getById(id));
	}

	@ApiOperation(value = "获取菜单列表", notes = "获取菜单分页列表")
	@PreAuthorize("hasAuthority('sys:menu:list')")
	@GetMapping("/list")
	public Result list() {
		// 使用BaseController中的getPage()方法获取分页参数
		Page<SysMenu> page = getPage();
		// 执行分页查询
		Page<SysMenu> pageData = sysMenuService.page(page);
    
		// 添加调试信息，查看菜单数据
	
    
		return Result.succ(200, "获取菜单分页列表成功", pageData);
	}

	@ApiOperation(value = "查询菜单", notes = "查询菜单")
	@PreAuthorize("hasAuthority('sys:menu:query')")
	@GetMapping("/query")
	public Result query() {
		// 复用list方法的分页逻辑
		return list();
	}

	@ApiOperation(value = "获取菜单树", notes = "获取菜单树形结构（用于展示层级关系）")
	@PreAuthorize("hasAuthority('sys:menu:list')")
	@GetMapping("/tree")
	public Result tree() {
		// 树形结构保持不变，用于特殊展示需求
		List<SysMenu> menus = sysMenuService.tree();

		return Result.succ(200, "获取菜单树形结构成功", menus);
	}

	@ApiOperation(value = "新增菜单", notes = "创建新菜单")
	@PostMapping("/add")
	@PreAuthorize("hasAuthority('sys:menu:add')")
	public Result add(@Validated @RequestBody SysMenu sysMenu) {

		sysMenu.setCreated(LocalDateTime.now());

		sysMenuService.save(sysMenu);
		return Result.succ(200, "创建菜单成功", sysMenu);
	}

	@ApiOperation(value = "更新菜单", notes = "更新菜单信息")
	@PutMapping("/update")
	@PreAuthorize("hasAuthority('sys:menu:update')")
	public Result update(@Validated @RequestBody SysMenu sysMenu) {

		sysMenu.setUpdated(LocalDateTime.now());

		sysMenuService.updateById(sysMenu);

		// 清除所有与该菜单相关的权限缓存
		sysUserService.clearUserAuthorityInfoByMenuId(sysMenu.getId());
		return Result.succ(200, "更新菜单成功", sysMenu);
	}

	@ApiOperation(value = "删除单个菜单", notes = "根据菜单ID删除菜单")
	@DeleteMapping("/delete/{id}")
	@PreAuthorize("hasAuthority('sys:menu:delete')")
	public Result deleteById(@PathVariable("id") Long id) {
		return delete(new Long[]{id});
	}

	@ApiOperation(value = "批量删除菜单", notes = "批量删除多个菜单")
	@DeleteMapping("/delete")
	@PreAuthorize("hasAuthority('sys:menu:delete')")
	public Result delete(@RequestBody Long[] ids) {
		for (Long id : ids) {
			int count = sysMenuService.count(new QueryWrapper<SysMenu>().eq("parent_id", id));
			if (count > 0) {
				return Result.fail("菜单下存在子菜单，删除失败");
			}
			
			// 清除所有与该菜单相关的权限缓存
			sysUserService.clearUserAuthorityInfoByMenuId(id);

			sysMenuService.removeById(id);

			// 同步删除中间关联表
			sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().eq("menu_id", id));
		}
		return Result.succ(200, "删除菜单成功", null);
	}
}
